package com.atguigu.gmall.common.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

@Component
public class RabbitService {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    //发消息   要求：发送失败之后 可以在交换机应答 队列应答处 可以重新发消息
    public void sendMessage(String exchange,String routingKey,Object msg){
        //子对象
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //首先生成UUID消息的唯一主键 32位
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //setId最终会被传入到message.messageProperties.header中
        gmallCorrelationData.setId(uuid);
        System.out.println("uuid:" + uuid);

        //gmallCorrelationData 继承了correlationData 扩展了几个成员变量
        //设置交换机
        gmallCorrelationData.setExchange(exchange);
        //设置routing
        gmallCorrelationData.setRoutingKey(routingKey);
        //设置消息
        gmallCorrelationData.setMessage(msg);

        //将gmallCorrelationData保存到redis缓存中
        //进行json转换就必须实现序列化接口 使用JSONObject转换则不需要实现序列化接口
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));
        //重发次数
        //发消息  4个参数  correlationData ：发送失败之后 将此 correlationData 返回到交换机应答 队列应答处
        //可以重新发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg,gmallCorrelationData);
    }

    //发送基于死信的延迟消息
    public void sendDeadLetterMessage(String exchange,String routingKey,Object msg,int ttl){
        //子对象
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //首先生成UUID消息的唯一主键 32位
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //setId最终会被传入到message.messageProperties.header中
        gmallCorrelationData.setId(uuid);
        System.out.println("uuid:" + uuid);

        //gmallCorrelationData 继承了correlationData 扩展了几个成员变量
        //设置交换机
        gmallCorrelationData.setExchange(exchange);
        //设置routing
        gmallCorrelationData.setRoutingKey(routingKey);
        //设置消息
        gmallCorrelationData.setMessage(msg);
        //是否是延迟消息
        gmallCorrelationData.setDelay(true);
        //延迟时长
        gmallCorrelationData.setDelayTime(ttl);

        //队列应答失败 准备存到redis中的缓存数据,用于重新发送消息
        redisTemplate.opsForValue().set(uuid,JSONObject.toJSONString(gmallCorrelationData));

        //发送延迟消息
        rabbitTemplate.convertAndSend(exchange,routingKey,msg, message -> {
            //在message.MessageProperties.expiration 设置ttl存活时间,指的是延迟消息延迟多少秒
            System.out.println(msg + "发送: " + new Date());
            message.getMessageProperties().setExpiration(String.valueOf(ttl * 1000));
            return message;
        },gmallCorrelationData);
    }

    //发送基于插件的自定义延迟消息
    public void sendDelayMessage(String exchange,String routingKey,Object msg,int delayTime){
        //子对象
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //首先生成UUID消息的唯一主键 32位
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //setId最终会被传入到message.messageProperties.header中
        gmallCorrelationData.setId(uuid);
        System.out.println("uuid:" + uuid);

        //gmallCorrelationData 继承了correlationData 扩展了几个成员变量
        //设置交换机
        gmallCorrelationData.setExchange(exchange);
        //设置routing
        gmallCorrelationData.setRoutingKey(routingKey);
        //设置消息
        gmallCorrelationData.setMessage(msg);
        //是否是延迟消息
        gmallCorrelationData.setDelay(true);
        //延迟时长
        gmallCorrelationData.setDelayTime(delayTime);

        //队列应答失败 准备存到redis中的缓存数据,用于重新发送消息
        redisTemplate.opsForValue().set(uuid,JSONObject.toJSONString(gmallCorrelationData));
        //发送延迟消息
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {
            //在message.MessageProperties.expiration 设置ttl存活时间,指的是延迟消息延迟多少秒
            System.out.println(msg + "发送: " + new Date());
            message.getMessageProperties().setDelay(delayTime * 1000); //设置延迟时间的单位是毫秒
            return message;
        },gmallCorrelationData);
    }

    @Autowired
    private RedisTemplate redisTemplate;
}
